/** * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.brixcms.markup; import org.apache.wicket.Component; import org.apache.wicket.MarkupContainer; import org.brixcms.jcr.wrapper.BrixNode; import org.brixcms.markup.tag.ComponentTag; import org.brixcms.markup.tag.Tag; import org.brixcms.plugin.site.SitePlugin; import org.brixcms.web.generic.IGenericComponent; import java.io.Serializable; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * Helper class for components with custom node markup. This class takes care of generating the markup and * creating/removing of appropriate wicket components. * * @author Matej Knopp */ public class MarkupHelper implements Serializable { /** * Each tag component ids prefixed by this. */ private final static String COMPONENT_PREFIX = "brix-"; private final IGenericComponent<BrixNode> component; private String markup = null; public MarkupHelper(IGenericComponent<BrixNode> component) { this.component = component; initMarkup(); } /** * Generates the markup and makes sure that the markup container contains all components generated by the {@link * ComponentTag}s in markup. Also removes components no longer present in markup. */ private void initMarkup() { final Set<String> components = new HashSet<String>(); GeneratedMarkup markup = getMarkupCache().getMarkup(component); MarkupRenderer renderer = new MarkupRenderer(markup.items, markup.doctype) { @Override void postprocessTagAttributes(Tag tag, Map<String, String> attributes) { // if during rendering we have a ComponentTag if (tag instanceof ComponentTag && tag.getType() != Tag.Type.CLOSE) { ComponentTag componentTag = (ComponentTag) tag; String id = getComponentID(componentTag); // check if the component already is in hierarchy if (getExistingComponents().contains(id)) { // just put the wicket:id attribute to component tag attributes.put("wicket:id", id); components.add(id); } else { // otherwise we need to create the component instance Component c = componentTag.getComponent(id, component.getModel()); if (c != null) { attributes.put("wicket:id", id); components.add(id); ((MarkupContainer) component).add(c); } } } } }; this.markup = renderer.render(); // go through existing components and remove those not present in // current markup for (String s : getExistingComponents()) { if (!components.contains(s)) { ((MarkupContainer) component).get(s).remove(); } } } /** * Returns existing tag components on page. * * @return */ private Set<String> getExistingComponents() { Set<String> result = new HashSet<String>(); Iterator<? extends Component> i = ((MarkupContainer) component).iterator(); while (i.hasNext()) { Component c = i.next(); if (c.getId().startsWith(COMPONENT_PREFIX)) { result.add(c.getId()); } } return result; } public static String getComponentID(ComponentTag tag) { String uid = tag.getUniqueTagId(); return COMPONENT_PREFIX + (uid != null ? uid.toString() : ""); } public String getMarkup() { return markup; } private MarkupCache getMarkupCache() { return SitePlugin.get().getMarkupCache(); } }